package edu.neu.cs6515.test.runner;

import java.util.List;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.java.contract.ContractAssertionError;

import edu.neu.cs6515.board.rules.Rule;
import edu.neu.cs6515.player.strategy.AbstractStrategy;
import edu.neu.cs6515.player.strategy.SimpleStepStrategy;
import edu.neu.cs6515.player.strategy.StrategyException;
import edu.neu.cs6515.turn.TurnProxy;
import edu.neu.cs6515.xml.Bad;
import edu.neu.cs6515.xml.Placement;
import edu.neu.cs6515.xml.Strategy;
import edu.neu.cs6515.xml.Tile;
import edu.neu.cs6515.xml.XMLTurnProxy;

/**
 * Testrunner for integration-tests of the Player
 */
public class PlayerTestRunner extends AbstractTestRunner {

    private XMLTurnProxy.Player xmlplayer;
    private XMLTurnProxy currentTurn;
    protected final List<Tile> tilesToBeHandedByAdmin;
    private boolean acceptNewTurnsOnBoard = true;

    /**
     * C'tor, executes turn if board initialization was okay
     * 
     * @param currentTurn
     *            turn to be executed
     */
    public PlayerTestRunner(final XMLTurnProxy currentTurn) {
        super(currentTurn.getBoard());
        this.currentTurn = currentTurn;
        xmlplayer = currentTurn.getPlayer();
        tilesToBeHandedByAdmin = currentTurn.getAdministrator().getTile();
        if (acceptNewTurnsOnBoard) {
            executeTurn();
        }
    }

    /**
     * Creates a player, strategy and executes a complete turn
     */
    public void executeTurn() {
        AbstractStrategy xmlbased = new SimpleStepStrategy(currentTurn
                .getActions().getPlacement());
        edu.neu.cs6515.player.Player gamePlayer = new edu.neu.cs6515.player.Player(
                "player1", xmlbased);
        gamePlayer.setPlayersInGame(
                Lists.newArrayList("player1", "the other player"));

        TurnProxy proxy = new TurnProxy(board, xmlplayer.getTile(),
                xmlplayer.getScore(), tilesToBeHandedByAdmin);

        try {
            gamePlayer.makeYourTurn(proxy);
            gameResults.setScore(Lists.newArrayList(proxy.getCurrentScore()));
        } catch (StrategyException e) {
            gameResults.getStrategy().add(new Strategy());
        } catch (ContractAssertionError e) {
            gameResults.getBad().add(new Bad(e.getMessage()));
        }
    }

    /**
     * Applies list of initial placements to board
     * 
     * @param placements
     *            Placements to init board
     */
    @Override
    protected void initializePlacements(final List<Placement> placements) {
        for (final Placement placement : placements) {
            List<Rule> brokenRules = board.getBrokenRules(placement);
            if (brokenRules.size() > 0) {
                gameResults.setBad(ImmutableList.of(new Bad(brokenRules.get(0)
                        .getReason())));
                acceptNewTurnsOnBoard = false;
                return;
            } else {
                board.updateHexagonBoard(placement);
            }
        }
    }

}
